/*	================================================================================
	$.Example.HideShow
	Author: 	Ben Haldenby
				
	Date:		2009-03-26
	Description:Hides and shows content
	================================================================================ */

	(function($) {
		
		/**
		* <p>Hides content on the page and then makes it show-able via a clickable trigger.</p>
		* 
		* <p>Script is activated by specifying which element to hide.</p>
		*
		* @example
		*	$.Example.start("hideshow", function(){
		*		$('div.myWidget').Example().HideShow();
		*	});
		* 
		* <p>The markup should follow this pattern:</p>
		*
		* <font color="#2040a0"><strong><font color="#4444ff"><strong><</strong></font><font color="#2040a0">div</font> <font color="#2040a0">class=</font><font color="#008000">"myWidget"</font><font color="#4444ff"><strong>></strong></font></strong></font>
		* <font color="#2040a0"><strong><font color="#4444ff"><strong><</strong></font><font color="#2040a0">div</font> <font color="#2040a0">class=</font><font color="#008000">"content"</font><font color="#4444ff"><strong>></strong></font></strong></font>
		* 		<font color="#2040a0"><strong><font color="#4444ff"><strong><</strong></font><font color="#2040a0">p</font><font color="#4444ff"><strong>></strong></font></strong></font>This content remains visible at all times.<font color="#2040a0"><strong><font color="#4444ff"><strong><</strong></font><font color="#2040a0">/p</font><font color="#4444ff"><strong>></strong></font></strong></font>
		* 		<font color="#2040a0"><strong><font color="#4444ff"><strong><</strong></font><font color="#2040a0">div</font> <font color="#2040a0">class=</font><font color="#008000">"hs_widget"</font><font color="#4444ff"><strong>></strong></font></strong></font>
		* 			<font color="#2040a0"><strong><font color="#4444ff"><strong><</strong></font><font color="#2040a0">p</font><font color="#4444ff"><strong>></strong></font></strong></font>This content is hidden by the script.<font color="#2040a0"><strong><font color="#4444ff"><strong><</strong></font><font color="#2040a0">/p</font><font color="#4444ff"><strong>></strong></font></strong></font>
		* 		<font color="#2040a0"><strong><font color="#4444ff"><strong><</strong></font><font color="#2040a0">/div</font><font color="#4444ff"><strong>></strong></font></strong></font>
		* 	<font color="#2040a0"><strong><font color="#4444ff"><strong><</strong></font><font color="#2040a0">/div</font><font color="#4444ff"><strong>></strong></font></strong></font>
		* 	<font color="#2040a0"><strong><font color="#4444ff"><strong><</strong></font><font color="#2040a0">p</font> <font color="#2040a0">class=</font><font color="#008000">"hs_trigger"</font><font color="#4444ff"><strong>></strong></font></strong></font><font color="#2040a0"><strong><font color="#4444ff"><strong><</strong></font><font color="#2040a0">a</font> <font color="#2040a0">href=</font><font color="#008000">"#"</font> <font color="#2040a0">rel=</font><font color="#008000">"hs_trigger"</font> <font color="#2040a0">class=</font><font color="#008000">"hs_vert closed"</font><font color="#4444ff"><strong>></strong></font></strong></font>This triggers the hide/show<font color="#2040a0"><strong><font color="#4444ff"><strong><</strong></font><font color="#2040a0">/a</font><font color="#4444ff"><strong>></strong></font></strong></font><font color="#2040a0"><strong><font color="#4444ff"><strong><</strong></font><font color="#2040a0">/p</font><font color="#4444ff"><strong>></strong></font></strong></font>
		* <font color="#2040a0"><strong><font color="#4444ff"><strong><</strong></font><font color="#2040a0">/div</font><font color="#4444ff"><strong>></strong></font></strong></font>
		* 
		* <p>The 'hs_vert' class can be transposed to 'hs_horiz' to create an horizontal transition effect.</p>
		*
		* <p>Creating multiple Hide/Shows is as simple as duplicating the entire markup block; nothing special is required. Simply call the HideShow() method on your common selector, ie: 'div.myWidget'.
		* 
		* <p>When JavaScript is disabled the entire content of the DIV is displayed except for the 'trigger' link, which is hidden.</p>
		* 
		* <p>Other examples of calling the script:</p>
		* 
		* @example
		*	$.Example.start("hideshow", function(){
		*		$('div.myWidget').Example().HideShow();
		*			showText:	'Reveal',
		*			hideText:	'Hide',
		*			transition:	'slide',
		*			speed:		'slow'
		*		})
		*	});
		*
		* <p>The default settings:</p>
		* <p>
		*	showText:	'Show more',
		*	<br />
		*	hideText:	'Show less',
		*	<br />
		*	transition:	'slide',
		*	<br />
		*	speed:		'fast'
		* </p>
		*
		* <p>Optional settings are:</p>
		* <p>
		*	showText:	'Any string',
		*	<br />
		*	hideText:	'Any string',
		*	<br />
		*	speed:		'fast' or 'slow' or specify in seconds (ie: 1)
		* </p>
		*	
		* @class
		* @param {Object} options See {@link $.fn.Example.HideShow.defaults } for more details
		*/
		$.fn.Example.HideShow = function(options) {
			var opts = $.extend({}, $.fn.Example.HideShow.defaults, options);
					
			// Find the widget inside the main element and hide it
			// $(this) = the main element that HideShow() was called on, ie: div#hsOne

			// If speed was passed in as seconds (ie: 2) then multiply it by 1000 to get milliseconds
			if (opts.speed != 'fast' & opts.speed != 'slow') {
				opts.speed *= 1000;
			}
			
			return $(this).each(function(){
				// Create reference to this widget (using 'var' is essential)
				var widget = $(this).find('div.hs_widget');
				$(this).find('div.hs_widget').each(function(){

					// If the widget is a Gallery then hide it by positioning it off-screen
					// this is because slideshow.js cannot determine the dimensions (w, h) of elements that are hidden with display:none
					//if ($(this).hasClass('hs_gallery')) {
					//	$(this).addClass('hs_offscreen');
					//} else {
						$(this).addClass('hideContent');
						//$(this).hide();
					//}
				});
					
				// Find the trigger inside the main element and show it
				$(this).find('.hs_trigger').show();
				
				// If custom text was passed in then apply it to the link
				if (options != undefined && options.showText != null) {
					$(this).find('.hs_trigger a').text(opts.showText);
				}
	
				// Loop through all of the links which trigger a widget to appear
				$(this).find('A[rel="hs_trigger"]').each(function(i) {
					// Use the in-built loop counter variable (i) to locate the trigger's matching widget
					var link = $(this);
					var linkText = $(link).text();

					// Use the jQuery toggle method
					$(this).toggle( 
						function() {
							// If there is no custom text for the link then use the default option:
							// Trim the link text and prepend 'Show' to the beginning
							if (options == undefined || options.showText == undefined) {
								opts.showText = $.fn.Example.HideShow.changeLabel(linkText, 'Show');
							}
							// If there is no custom text for the link then use the default option:
							// Trim the link text and prepend 'Hide' to the beginning
							if (options == undefined || options.hideText == undefined) {
								opts.hideText = $.fn.Example.HideShow.changeLabel(linkText, 'Hide');
							}
							// Pass the link that triggers the reveal and the corresponding widget to the $.fn.HideShow.show() method
							$.fn.Example.HideShow.show(link, widget, opts.hideText, opts.transition, opts.speed);
						}, 
						function() { 
							// Pass the link that triggers the hide and the corresponding widget to the $.fn.HideShow.hide() method
							$.fn.Example.HideShow.hide(link, widget, opts.showText, opts.transition, opts.speed);
						} 
					); 
				});
			});
				
			
		};
		
		
		/**
		* This private method is used to SHOW the hidden widget content. It accepts two parameters: a reference to the link that triggers the reveal and a reference to the widget that should be shown. It reveals the hidden widget content using jQuery animation effects and changes the text in the trigger label, ie: 'Show...' becomes 'Hide...'.
		* @param {string} link A DOM reference to the A element that is triggering the widget to reveal.
		* @param {string} widget A DOM reference to the element that contains the hidden widget content.
		* @example $.fn.HideShow.show(link, widget);
		* @private
		*/
		$.fn.Example.HideShow.show = function(link, widget, newLabel, transition, speed) {
			// Bring the gallery widget back on to the screen
			// but we still add hideContent to retain the transition effect
			
			if ($(widget).hasClass('hs_offscreen')) {
				$(widget).removeClass('hs_offscreen');
				$(widget).addClass('hideContent');
			}

			// Change the direction of the arrow next to the trigger link
			$(link).removeClass('closed');
			$(link).addClass('open');
			
			// Change the label of the trigger
			if($(link).hasClass('nolabel')) {
				// do nothing
			} else {
				$(link).text(newLabel);
			}

			if (transition == 'slide') {
				$(widget).slideToggle(speed);
			}
			widget.removeClass('hideContent');
			
		};


		/**
		* This private method is used to HIDE the hidden widget content. It accepts two parameters: a reference to the link that triggers the hide and a reference to the widget that should be hidden. It hides the widget content using jQuery animation effects and changes the text in the trigger label, ie: 'Hide...' becomes 'Show...'.
		* @param {string} link A DOM reference to the A element that is triggering the widget to reveal.
		* @param {string} widget A DOM reference to the element that contains the hidden widget content.
		* @example $.fn.HideShow.hide(link, widget);
		* @private
		*/
		$.fn.Example.HideShow.hide = function(link, widget, newLabel, transition, speed) {
			
			if ($(widget).hasClass('hs_offscreen')) {
				$(widget).removeClass('hs_offscreen');
				$(widget).addClass('hideContent');
			}
			
			// Change the direction of the arrow next to the trigger link
			$(link).removeClass('open');
			$(link).addClass('closed');
			
			// Change the label of the trigger
			if($(link).hasClass('nolabel')) {
				// do nothing
			} else {
				$(link).text(newLabel);
			}
			
			if (transition == 'slide') {
				$(widget).slideToggle(speed);
			}

		};
		
		
		/**
		* This private method is used to change the label of the trigger. It accepts two parameters: the entire text to be modified (the existing label) and the prefix to be applied ('Hide' or 'Show'). The new, modified string is returned.
		* @param {string} text The string to be modified.
		* @param {string} prefix The word to be inserted.
		* @example $.Example.HideShow.changeLabel('Show this widget', 'Hide');
		* @private
		*/
		$.fn.Example.HideShow.changeLabel = function(text, prefix) {
			var $label = text;
			len = $label.length;
			$label = $label.substring(5, len);
			$label = prefix + ' ' + $label;
			return $label;
		}
		
		/**
		 * <p>The default settings for the HideShow.  These can be overridden by inputting options if needed:</p>
		 * 
		 * <ul>
		 * 	<li>showText - Sets the text on the link when the content is hidden.</li>
		 * 	<li>hideText - Sets the text on the link when the content is shown.</li>
		 * 	<li>transition - Sets the transition effect to use. At present only 'slide' is implemented.</li>
		 * 	<li>speed - The speed to use when hiding or showing content.</li>
		 * </ul>
		 */		
		$.fn.Example.HideShow.defaults = {
			showText:	'Show more',
			hideText:	'Show less',
			transition:	'slide',
			speed:		'fast'
		};
		
	})(jQuery);